/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "log/Log.h"
// #include "stub.h"
#include "named_stub.h"
#include "ArchiveDownloadFile.h"
#include "Backup.h"
#include "ScanMgr.h"
#include "PluginUtilities.h"
#include "NasArchiveRestore.h"
#include "statistics/ShareResourceManager.h"
#include "SmbContextWrapper.h"
#include "SnapdiffService.h"
#include "NfsContextWrapper.h"
#include "device_access/dorado/DoradoBlock.h"

#include "gtest/gtest.h"
#include "mockcpp/mockcpp.hpp"

using ::testing::_;
using ::testing::AtLeast;
using testing::DoAll;
using testing::InitGoogleMock;
using ::testing::Return;
using ::testing::Sequence;
using ::testing::SetArgReferee;
using ::testing::Throw;
using namespace std;
using namespace FS_Backup;
using namespace Module;

namespace {
// const int SUCCESS = 0;
// const int FAILED = -1;

struct FileSetInfo {
    std::string filters;
    std::string paths;
    std::string templateId;
    std::string templateName;
    std::string shareMode;
    std::string shareIp;

    BEGIN_SERIAL_MEMEBER
    SERIAL_MEMBER_TO_SPECIFIED_NAME(filters, filters)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(paths, paths)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(templateId, templateId)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(templateName, templateName)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(shareMode, shareMode)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(shareIp, shareIp)
    END_SERIAL_MEMEBER
};

struct IpPort {
    std::string ip;
    int port { -1 };
    BEGIN_SERIAL_MEMEBER
    SERIAL_MEMBER_TO_SPECIFIED_NAME(ip, ip)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(port, port)
    END_SERIAL_MEMEBER
};

struct ExtendArchiveInfo {
    std::vector<IpPort> serviceInfo;
    bool enableSSL {false};
    BEGIN_SERIAL_MEMEBER
    SERIAL_MEMBER_TO_SPECIFIED_NAME(enableSSL, enable_ssl)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(serviceInfo, service_info)
    END_SERIAL_MEMEBER
};

// formatTypeTag: 控制formatType，从而控制m_isAggCopy
AppProtect::RestoreJob RestoreJobInfoSetUp(bool formatTypeTag, string FileOrShare)
{
    AppProtect::RestoreJob restoreJob;
    restoreJob.requestId = "123456789";
    restoreJob.jobId = "111111";
    restoreJob.targetEnv.id = "123";
    restoreJob.targetEnv.name = "123";
    restoreJob.targetEnv.port = 8088;
    restoreJob.targetEnv.auth.authkey = "admin";
    restoreJob.targetEnv.auth.authPwd = "Huawei@123456789";
    restoreJob.targetEnv.subType = "1";
    restoreJob.targetObject.id = "123";
    restoreJob.targetObject.name = "123";
    restoreJob.targetObject.parentId =" 4564654645564";
    restoreJob.targetObject.parentName = "test_filesystem";
    // restoreJob.targetObject.subType ="NasShare";  // 控制参数
    restoreJob.targetObject.subType = FileOrShare;
    restoreJob.targetEnv.endpoint = "127.0.0.1";
    restoreJob.targetObject.auth.authkey = "admin";
    restoreJob.targetObject.auth.authPwd = "Huawei@123456789";
    // restoreJob.targetObject.extendInfo = "{\"authMode\":\"1\",\"filters\":\"\",\"ip\":\"10.28.12.144\""
    //                                      ",\"kerberosId\":\"0\",\"shareMode\":\"1\"}";
    
    FileSetInfo fileSetInfo;
    fileSetInfo.filters = "";
    fileSetInfo.paths = "[{\"name\":\"/l30015744_restore\"}]";
    fileSetInfo.templateId = "";
    fileSetInfo.templateName = "";
    fileSetInfo.shareMode = "0";
    fileSetInfo.shareIp = "192.168.34.52";

    std::string filesetInfoStr;
    Module::JsonHelper::StructToJsonString(fileSetInfo, filesetInfoStr);
    restoreJob.targetEnv.extendInfo = filesetInfoStr;
    restoreJob.targetObject.extendInfo = filesetInfoStr;

    std::string path = "/MetaFS/cache";
    HostAddress hostadd;
    hostadd.ip="10.28.12.144";
    StorageRepository cacheRepo;
    cacheRepo.repositoryType = RepositoryDataType::CACHE_REPOSITORY;
    cacheRepo.path.push_back(path);
    cacheRepo.remotePath = "/MetaFS/cache";
    cacheRepo.remoteHost.push_back(hostadd);
    cacheRepo.auth.authkey = "admin";
    cacheRepo.auth.authPwd = "Admin@123";
    cacheRepo.endpoint.ip = "10.28.12.144";
    cacheRepo.endpoint.port = 8088;
    StorageRepository dataRepo;
    dataRepo.repositoryType = RepositoryDataType::DATA_REPOSITORY;
    dataRepo.remotePath = "/BackupFS";
    dataRepo.path.push_back(dataRepo.remotePath);
    dataRepo.remoteHost.push_back(hostadd);
    dataRepo.auth.authkey = "admin";
    dataRepo.auth.authPwd = "Admin@123";
    dataRepo.endpoint.ip = "10.28.12.144";
    dataRepo.endpoint.port = 8088;
    dataRepo.protocol = RepositoryProtocolType::type::S3;

    ExtendArchiveInfo archiveInfo;

    IpPort port;
    port.ip = "192.168.34.52";
    port.port = 57577;

    archiveInfo.serviceInfo.push_back(port);
    archiveInfo.enableSSL = false;

    std::string archiveInfoStr;
    Module::JsonHelper::StructToJsonString(archiveInfo, archiveInfoStr);

    dataRepo.extendInfo = archiveInfoStr;
    StorageRepository metaRepo;
    metaRepo.repositoryType = RepositoryDataType::META_REPOSITORY;
    path = "/MetaFS/meta";
    metaRepo.path.push_back(path);
    metaRepo.remotePath = "/MetaFS/meta";
    metaRepo.remoteHost.push_back(hostadd);
    metaRepo.auth.authkey = "admin";
    metaRepo.auth.authPwd = "Admin@123";
    metaRepo.endpoint.ip = "10.28.12.144";
    metaRepo.endpoint.port = 8088;

    Copy copy;
    copy.repositories.push_back(cacheRepo);
    copy.repositories.push_back(dataRepo);
    copy.repositories.push_back(metaRepo);
    copy.id = "copyId";
    copy.protectObject.id = "CopyProtectObjectId";
    copy.protectObject.subType = FileOrShare;  //控制参数
    if (formatTypeTag) {
        copy.formatType = CopyFormatType::type::INNER_DIRECTORY;
    }
    restoreJob.copies.push_back(copy);
    restoreJob.extendInfo = "{\"failed_script\":\"\",\"post_script\":\"\",\"pre_script\":\"\","
                           "\"restoreOption\":\"SKIP\", \"protocol\":\"0\"}";
    return restoreJob;
}
}

namespace Archive_Test2 {
    class BackupTest : public Backup {
    public:
        explicit BackupTest(const BackupParams& backupParams);
        BackupTest(std::string source, std::string destination);
        ~BackupTest() override;

        BackupRetCode Start() override;
        BackupRetCode Abort() override;
        BackupRetCode Destroy() override;
        BackupRetCode Enqueue(std::string contrlFile) override;
        BackupPhaseStatus GetStatus() override;
        BackupStats GetStats() override;
        std::unordered_set<FailedRecordItem, FailedRecordItemHash> GetFailedDetails() override;
    };


    BackupTest::BackupTest(const BackupParams& backupParams) :  Backup(backupParams) {};

    BackupTest::~BackupTest() {};

    BackupRetCode BackupTest::Start() {
        return BackupRetCode::SUCCESS;
    }
    BackupRetCode BackupTest::Abort() {
        return BackupRetCode::SUCCESS;
    }
    BackupRetCode BackupTest::Destroy() {
        return BackupRetCode::SUCCESS;
    }
    BackupRetCode BackupTest::Enqueue(std::string contrlFile) {
        return BackupRetCode::SUCCESS;
    }
    BackupPhaseStatus BackupTest::GetStatus() {
        return BackupPhaseStatus::COMPLETED;
    }
    BackupStats BackupTest::GetStats() {
        BackupStats backupStats;
        return backupStats;
    }
    std::unordered_set<FailedRecordItem, FailedRecordItemHash> BackupTest::GetFailedDetails() {
        std::unordered_set<FailedRecordItem, FailedRecordItemHash> ret;
        return ret;
    }
    class ScanTest : public Scanner {
    public:
        explicit ScanTest(const ScanConfig& scanConfig);
        ~ScanTest() override;

        SCANNER_STATUS Start() override;
        SCANNER_STATUS Abort() override;
        SCANNER_STATUS Destroy() override;
        SCANNER_STATUS Enqueue(const std::string& directory, const std::string& prefix = "", uint8_t filterFlag = 0) override;
        SCANNER_STATUS EnqueueV2(const std::string& directory) override;
        SCANNER_STATUS GetStatus() override;
        ScanStatistics GetStatistics() override;
        ErrRecorder QueryFailure() override;
    };

    ScanTest::ScanTest(const ScanConfig& scanConfig) : Scanner(scanConfig) {};

    ScanTest::~ScanTest() {};

    SCANNER_STATUS ScanTest::Start() {
        return SCANNER_STATUS::SUCCESS;
    }
    SCANNER_STATUS ScanTest::Abort() {
        return SCANNER_STATUS::SUCCESS;
    }
    SCANNER_STATUS ScanTest::Destroy() {
        return SCANNER_STATUS::SUCCESS;
    }
    SCANNER_STATUS ScanTest::Enqueue(const std::string& directory, const std::string& prefix, uint8_t filterFlag) {
        return SCANNER_STATUS::SUCCESS;
    }
    SCANNER_STATUS ScanTest::EnqueueV2(const std::string& directory) {
        return SCANNER_STATUS::SUCCESS;
    }
    SCANNER_STATUS ScanTest::GetStatus() {
        return SCANNER_STATUS::COMPLETED;
    }
    ScanStatistics ScanTest::GetStatistics() {
        ScanStatistics scanStats {};
        return scanStats;
    }
    
    ErrRecorder ScanTest::QueryFailure() {
        ErrRecorder errRecorder {};
        return errRecorder;
    }
}// namespace archive_test

static unique_ptr<FS_Backup::Backup> CreateBackupInstStub_Succ(void* obj, BackupParams backupParams) {
    BackupParams emptyInfo;
    return std::make_unique<Archive_Test2::BackupTest>(emptyInfo);
}

static unique_ptr<Scanner> CreateScanInstStub_Succ(void* obj, const ScanConfig& scanConfig) {
    ScanConfig emptInfo;
    unique_ptr<Scanner> scanInst = std::make_unique<Archive_Test2::ScanTest>(emptInfo);
    return scanInst;
}

static AppProtect::SubJob GetSubJob()
{
    AppProtect::SubJob subJob;
    subJob.jobId = "jobId123";
    subJob.subJobId = "subJob123";
    subJob.jobName = "subJob";
    subJob.jobPriority = 1;
    subJob.ignoreFailed = true;
    subJob.execNodeId = "abcde";
    subJob.jobInfo = "{\"ControlFile\":\"/cache/livemount-job/scan/ctrl\","
                    "\"SubTaskType\":1,"
                    "\"Ext\":\"abc\"}";
    return subJob;
}

static void StubFunction_VOID(void *ob)
{}

static bool StubFunction_TRUE(void *ob)
{
    return true;
}

class NasArchiveRestoreTest2 : public testing::Test {
public:
    void SetUp();
    void TearDown();
    static void SetUpTestCase();
    static void TearDownTestCase();
    void SetUpResourceManagerFunc();
    std::unique_ptr<NasArchiveRestore> m_restoreJob = std::make_unique<NasArchiveRestore>();
    LLTSTUB::Stub stub; // stub and mockcpp
};

static bool StubOperateIpsRule(std::vector<std::string>& ipList, const std::string& operation)
{
    return true;
}

void NasArchiveRestoreTest2::SetUp()
{
    AppProtect::SubJob subJob = GetSubJob();
    m_restoreJob->SetSubJob(std::make_shared<SubJob>(subJob));
    stub.set(ADDR(PluginUtils, OperateIpsRule), StubOperateIpsRule);

}

void NasArchiveRestoreTest2::TearDown() 
{
    GlobalMockObject::verify(); // 校验mock规范并清除mock规范
}

void NasArchiveRestoreTest2::SetUpTestCase() {}
void NasArchiveRestoreTest2::TearDownTestCase() {}

/*
 * 用例名称: InitInfo
 * 前置条件：
 * check点：初始化信息
 */
TEST_F(NasArchiveRestoreTest2, InitInfo)
{
    AppProtect::RestoreJob restoreJob = RestoreJobInfoSetUp(false, "NasShare");
    auto jobInfoRestore = make_shared<JobCommonInfo>(make_shared<RestoreJob>(restoreJob));
    m_restoreJob->SetJobInfo(jobInfoRestore);
    m_restoreJob->InitJobInfo();
    MOCKER_CPP(&NasArchiveRestore::InitJobInfo)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    MOCKER_CPP(&NasArchiveRestore::InitRepoInfo)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    MOCKER_CPP(&NasArchiveRestore::InitRestoreInfo)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    MOCKER_CPP(&NasArchiveRestore::InitArchiveInfo)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    MOCKER_CPP(&NasArchiveRestore::InitProtocolInfo)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));

    EXPECT_EQ(m_restoreJob->InitInfo(), false);
    EXPECT_EQ(m_restoreJob->InitInfo(), false);  
    EXPECT_EQ(m_restoreJob->InitInfo(), false);  
    EXPECT_EQ(m_restoreJob->InitInfo(), false);  
    EXPECT_EQ(m_restoreJob->InitInfo(), false);  
    EXPECT_EQ(m_restoreJob->InitInfo(), true);   
}

/*
 * 用例名称: InitProtocolInfo
 * 前置条件：
 * check点：初始化信息
 */
TEST_F(NasArchiveRestoreTest2, InitProtocolInfo)
{
    AppProtect::RestoreJob restoreJob = RestoreJobInfoSetUp(false, "NasShare");
    auto jobInfoRestore = make_shared<JobCommonInfo>(make_shared<RestoreJob>(restoreJob));
    m_restoreJob->SetJobInfo(jobInfoRestore);
    m_restoreJob->InitJobInfo();
    MOCKER_CPP(&NasArchiveRestore::InitRestoreInfoFileSystem)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    MOCKER_CPP(&NasArchiveRestore::InitRestoreInfoNasShare)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    MOCKER_CPP(&NasArchiveRestore::IsRestoreByCIFS)
            .stubs()
            .will(returnValue(true))
            .then(returnValue(false));
    m_restoreJob->m_jobInfoPtr->targetObject.subType = "NasFileSystem";
    EXPECT_EQ(m_restoreJob->InitProtocolInfo(), false);
    m_restoreJob->m_jobInfoPtr->targetObject.subType = "NasShare";
    EXPECT_EQ(m_restoreJob->InitProtocolInfo(), false); 
    EXPECT_EQ(m_restoreJob->InitProtocolInfo(), false);
    m_restoreJob->m_nasShare.protocol = "a";   
    EXPECT_EQ(m_restoreJob->InitProtocolInfo(), true);     
}

/*
 * 用例名称: CheckAvailableShareInfo
 * 前置条件：
 * check点：检查共享信息
 */
TEST_F(NasArchiveRestoreTest2, CheckAvailableShareInfo)
{
    AppProtect::RestoreJob restoreJob = RestoreJobInfoSetUp(false, "NasShare");
    auto jobInfoRestore = make_shared<JobCommonInfo>(make_shared<RestoreJob>(restoreJob));
    m_restoreJob->SetJobInfo(jobInfoRestore);
    m_restoreJob->InitJobInfo();
    MOCKER_CPP(&NasArchiveRestore::IsRestoreByNFS)
            .stubs()
            .will(returnValue(true))
            .then(returnValue(true))
            .then(returnValue(false));
    MOCKER_CPP(&NasArchiveRestore::CheckConnectNFS)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    MOCKER_CPP(&NasArchiveRestore::IsRestoreByCIFS)
            .stubs()
            .will(returnValue(true))
            .then(returnValue(true))
            .then(returnValue(false));
    MOCKER_CPP(&NasArchiveRestore::GetAvailableIpSMB)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    EXPECT_EQ(m_restoreJob->CheckAvailableShareInfo(), false);
    EXPECT_EQ(m_restoreJob->CheckAvailableShareInfo(), true); 
    EXPECT_EQ(m_restoreJob->CheckAvailableShareInfo(), false); 
    EXPECT_EQ(m_restoreJob->CheckAvailableShareInfo(), true);  
    EXPECT_EQ(m_restoreJob->CheckAvailableShareInfo(), false);    
}

/*
 * 用例名称: CheckConnectNFS
 * 前置条件：
 * check点：检查连接
 */
TEST_F(NasArchiveRestoreTest2, CheckConnectNFS)
{
    AppProtect::RestoreJob restoreJob = RestoreJobInfoSetUp(false, "NasShare");
    auto jobInfoRestore = make_shared<JobCommonInfo>(make_shared<RestoreJob>(restoreJob));
    m_restoreJob->SetJobInfo(jobInfoRestore);
    m_restoreJob->InitJobInfo();
    MOCKER_CPP(&PluginUtils::MountNFS)
            .stubs()
            .will(returnValue(-1))
            .then(returnValue(0));
    MOCKER_CPP(&PluginUtils::UnmountNas)
            .stubs()
            .will(returnValue(-1))
            .then(returnValue(0));
    MOCKER_CPP(&Module::NfsContextWrapper::NfsMount)
            .stubs()
            .will(returnValue(-1))
            .then(returnValue(0));
    MOCKER_CPP(&Module::NfsContextWrapper::GetNfsReadMaxSizeLock)
            .stubs()
            .will(ignoreReturnValue());
    MOCKER_CPP(&Module::NfsContextWrapper::GetNfsWriteMaxSizeLock)
            .stubs()
            .will(ignoreReturnValue());
    std::string protoVersion;
    EXPECT_EQ(m_restoreJob->CheckConnectNFS(protoVersion), false);
    EXPECT_EQ(m_restoreJob->CheckConnectNFS(protoVersion), false);
    EXPECT_EQ(m_restoreJob->CheckConnectNFS(protoVersion), true);
    EXPECT_EQ(m_restoreJob->CheckConnectNFS(protoVersion), true);
}

/*
 * 用例名称: CheckConnectSMB
 * 前置条件：
 * check点：检查连接
 */
TEST_F(NasArchiveRestoreTest2, CheckConnectSMB)
{
    AppProtect::RestoreJob restoreJob = RestoreJobInfoSetUp(false, "NasShare");
    auto jobInfoRestore = make_shared<JobCommonInfo>(make_shared<RestoreJob>(restoreJob));
    m_restoreJob->SetJobInfo(jobInfoRestore);
    m_restoreJob->InitJobInfo();
    std::string ip;
    Module::SmbVersion version;
    m_restoreJob->m_nasShare.auth.authType = AuthType::type::OTHER;
    EXPECT_EQ(m_restoreJob->CheckConnectSMB(ip, version), false);
    m_restoreJob->m_nasShare.auth.authType = AuthType::type::KERBEROS;
    EXPECT_EQ(m_restoreJob->CheckConnectSMB(ip, version), false);
    m_restoreJob->m_nasShare.auth.authType = AuthType::type::NO_AUTHENTICATION;
    EXPECT_EQ(m_restoreJob->CheckConnectSMB(ip, version), false); 
    m_restoreJob->m_nasShare.auth.authType = AuthType::type::OS_PASSWORD;
    EXPECT_EQ(m_restoreJob->CheckConnectSMB(ip, version), false); 
    m_restoreJob->m_nasShare.auth.authType = AuthType::type::APP_PASSWORD;
    EXPECT_EQ(m_restoreJob->CheckConnectSMB(ip, version), false);     
}

/*
 * 用例名称: FillIplistForNativeRestore
 * 前置条件：
 * check点：检查连接
 */
TEST_F(NasArchiveRestoreTest2, FillIplistForNativeRestore1)
{
    AppProtect::RestoreJob restoreJob = RestoreJobInfoSetUp(false, "NasShare");
    auto jobInfoRestore = make_shared<JobCommonInfo>(make_shared<RestoreJob>(restoreJob));
    // copies空
    m_restoreJob->SetJobInfo(jobInfoRestore);
    m_restoreJob->InitJobInfo();
    m_restoreJob->m_jobInfoPtr->copies.clear();
    EXPECT_EQ(m_restoreJob->FillIplistForNativeRestore(), false);
}

/*
 * 用例名称: FillIplistForNativeRestore
 * 前置条件：
 * check点：检查连接
 */
TEST_F(NasArchiveRestoreTest2, FillIplistForNativeRestore2)
{
    AppProtect::RestoreJob restoreJob = RestoreJobInfoSetUp(false, "NasShare");
    auto jobInfoRestore = make_shared<JobCommonInfo>(make_shared<RestoreJob>(restoreJob));

    // copies非空
    m_restoreJob->SetJobInfo(jobInfoRestore);
    m_restoreJob->InitJobInfo();
    EXPECT_EQ(m_restoreJob->FillIplistForNativeRestore(), true);
}

/*
 * 用例名称: InitCacheRepoDir
 * 前置条件：
 * check点：初始化cache目录
 */
TEST_F(NasArchiveRestoreTest2, InitCacheRepoDir)
{
    AppProtect::RestoreJob restoreJob = RestoreJobInfoSetUp(false, "NasShare");
    auto jobInfoRestore = make_shared<JobCommonInfo>(make_shared<RestoreJob>(restoreJob));
    m_restoreJob->SetJobInfo(jobInfoRestore);
    m_restoreJob->InitJobInfo();
    MOCKER_CPP(&PluginUtils::RecurseCreateDirectory)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    MOCKER_CPP(&NasArchiveRestore::InitMainResources)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    MOCKER_CPP(&NasArchiveRestore::QueryMainScanResources)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    EXPECT_EQ(m_restoreJob->InitCacheRepoDir(), false); 
    EXPECT_EQ(m_restoreJob->InitCacheRepoDir(), false); 
    EXPECT_EQ(m_restoreJob->InitCacheRepoDir(), false); 
    EXPECT_EQ(m_restoreJob->InitCacheRepoDir(), true);   
}

/*
 * 用例名称: CopyMetaFile
 * 前置条件：
 * check点：复制metafile文件
 */
TEST_F(NasArchiveRestoreTest2, CopyMetaFile)
{
    AppProtect::RestoreJob restoreJob = RestoreJobInfoSetUp(false, "NasShare");
    auto jobInfoRestore = make_shared<JobCommonInfo>(make_shared<RestoreJob>(restoreJob));
    m_restoreJob->SetJobInfo(jobInfoRestore);
    m_restoreJob->InitJobInfo();
    MOCKER_CPP(&PluginUtils::CreateDirectory)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    MOCKER_CPP(&Module::runShellCmdWithOutput)
            .stubs()
            .will(returnValue(-1))
            .then(returnValue(0));
    EXPECT_EQ(m_restoreJob->CopyMetaFile(), false); 
    EXPECT_EQ(m_restoreJob->CopyMetaFile(), false);  
    EXPECT_EQ(m_restoreJob->CopyMetaFile(), true);   
}

/*
 * 用例名称: PrepareMetaFile
 * 前置条件：
 * check点：准备metafile文件
 */
TEST_F(NasArchiveRestoreTest2, PrepareMetaFile)
{
    AppProtect::RestoreJob restoreJob = RestoreJobInfoSetUp(false, "NasShare");
    auto jobInfoRestore = make_shared<JobCommonInfo>(make_shared<RestoreJob>(restoreJob));
    m_restoreJob->SetJobInfo(jobInfoRestore);
    m_restoreJob->InitJobInfo();
    MOCKER_CPP(&NasArchiveRestore::IsNasShareCopy)
            .stubs()
            .will(returnValue(true))
            .then(returnValue(true))
            .then(returnValue(false));
    MOCKER_CPP(&NasArchiveRestore::UnzipOldMetafileZip)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    MOCKER_CPP(&NasArchiveRestore::IsFileSystemCopy)
            .stubs()
            .will(returnValue(true))
            .then(returnValue(true))
            .then(returnValue(false));
    MOCKER_CPP(&NasArchiveRestore::CopyMetaFile)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    EXPECT_EQ(m_restoreJob->PrepareMetaFile(), false);
    EXPECT_EQ(m_restoreJob->PrepareMetaFile(), false);
    EXPECT_EQ(m_restoreJob->PrepareMetaFile(), false);
    EXPECT_EQ(m_restoreJob->PrepareMetaFile(), true);
    EXPECT_EQ(m_restoreJob->PrepareMetaFile(), false);
}

/*
 * 用例名称: GenerateSubJobInner
 * 前置条件：
 * check点：准备metafile文件
 */
TEST_F(NasArchiveRestoreTest2, GenerateSubJobInner)
{
    AppProtect::RestoreJob restoreJob = RestoreJobInfoSetUp(false, "NasShare");
    auto jobInfoRestore = make_shared<JobCommonInfo>(make_shared<RestoreJob>(restoreJob));
    m_restoreJob->SetJobInfo(jobInfoRestore);
    m_restoreJob->InitJobInfo();
    MOCKER_CPP(&NasArchiveRestore::InitInfo)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    MOCKER_CPP(&NasArchiveRestore::InitCacheRepoDir)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    MOCKER_CPP(&NasArchiveRestore::DownloadMetaFile)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    MOCKER((std::this_thread::sleep_for<int64_t, std::ratio<1>>)) 
            .stubs() 
            .will(ignoreReturnValue());
    m_restoreJob->m_isPrepareMetaFinish = false;
    EXPECT_EQ(m_restoreJob->GenerateSubJobInner(), -1); 
    EXPECT_EQ(m_restoreJob->GenerateSubJobInner(), -1); 
    EXPECT_EQ(m_restoreJob->GenerateSubJobInner(), -1); 
    EXPECT_EQ(m_restoreJob->GenerateSubJobInner(), -1);   
}

/*
 * 用例名称: PrerequisiteJobInner
 * 前置条件：
 * check点：前置工作
 */
TEST_F(NasArchiveRestoreTest2, PrerequisiteJobInner)
{
    AppProtect::RestoreJob restoreJob = RestoreJobInfoSetUp(false, "NasShare");
    auto jobInfoRestore = make_shared<JobCommonInfo>(make_shared<RestoreJob>(restoreJob));
    m_restoreJob->SetJobInfo(jobInfoRestore);
    m_restoreJob->InitJobInfo();
    MOCKER_CPP(&NasArchiveRestore::InitInfo)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    MOCKER_CPP(&NasArchiveRestore::InitArchiveClient)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    MOCKER_CPP(&NasArchiveRestore::PrintInfo)
            .stubs()
            .will(ignoreReturnValue());
    EXPECT_EQ(m_restoreJob->PrerequisiteJobInner(), -1); 
    EXPECT_EQ(m_restoreJob->PrerequisiteJobInner(), -1);   
}

/*
* 用例名称：测试删除文件名前缀 、
* 前置条件：文件名带有多个 ///
* check点：去除文件名前缀的 ///
*/
TEST_F(NasArchiveRestoreTest2, CutPrefixSlash)
{
    AppProtect::RestoreJob restoreJob = RestoreJobInfoSetUp(false, "NasShare");
    auto jobInfoRestore = make_shared<JobCommonInfo>(make_shared<RestoreJob>(restoreJob));
    m_restoreJob->SetJobInfo(jobInfoRestore);
    m_restoreJob->InitJobInfo();
    std::string input = "///123.txt";
    std::string output = m_restoreJob->CutPrefixSlash(input);
    EXPECT_EQ(output, "123.txt");

    input = "///dir/123";
    output = m_restoreJob->CutPrefixSlash(input);
    EXPECT_EQ(output, "dir/123");

    input = "./dir/123";
    output = m_restoreJob->CutPrefixSlash(input);
    EXPECT_EQ(output, "dir/123");

    input = ".dir/123";
    output = m_restoreJob->CutPrefixSlash(input);
    EXPECT_EQ(output, "dir/123");

    input = ".//dir/123";
    output = m_restoreJob->CutPrefixSlash(input);
    EXPECT_EQ(output, "dir/123");
}

TEST_F(NasArchiveRestoreTest2, RemoveShareName)
{
    std::string input = "/Fileset_CacheDataRepository_su0/source_policy_07bc7411-4193-4a53-a88d-1d1cb6ae51cd/Context";
    std::string output = m_restoreJob->RemoveShareName(input);
    EXPECT_EQ(output, "source_policy_07bc7411-4193-4a53-a88d-1d1cb6ae51cd/Context");

    input = "/Fileset_CacheDataRepository_su0/source_policy_07bc7411-4193-4a53-a88d-1d1cb6ae51cd_Context";
    output = m_restoreJob->RemoveShareName(input);
    EXPECT_EQ(output, "source_policy_07bc7411-4193-4a53-a88d-1d1cb6ae51cd_Context");

    input = "/Fileset_CacheDataRepository_su0/07bc7411-4193-4a53-a88d-1d1cb6ae51cd";
    output = m_restoreJob->RemoveShareName(input);
    EXPECT_EQ(output, "");
}

TEST_F(NasArchiveRestoreTest2, SetArchiveSourceInfo)
{
    // Arrange
    std::string extendInfo = "{\"repositories\":[{\"type\":1,\"remotePath\":[{\"type\":0,\"path\":\"" \
    "/Fileset_CacheDataRepository_su0/source_policy_07bc7411-4193-4a53-a88d-1d1cb6ae51cd/Context\"}," \
    "{\"type\":1,\"path\":\"/Fileset_CacheDataRepository_su0/source_policy_07bc7411-4193-4a53-a88d-" \
    "1d1cb6ae51cd_Context\"}]}, {\"type\":0,\"remotePath\":[{\"type\":0,\"path\":\"" \
    "/Fileset_CacheDataRepository_su0/source_policy_07bc7411-4193-4a53-a88d-1d1cb6ae51cd/Context\"}," \
    "{\"type\":1,\"path\":\"/Fileset_CacheDataRepository_su0/source_policy_07bc7411-4193-4a53-a88d-" \
    "1d1cb6ae51cd_Context\"}]}]}";
    // Act
    // Assuming m_jobInfoPtr is a member of the class and is set to a valid object
    AppProtect::RestoreJob restoreJob = RestoreJobInfoSetUp(false, "NasShare");
    restoreJob.copies[0].extendInfo = extendInfo;
    auto jobInfoRestore = make_shared<JobCommonInfo>(make_shared<RestoreJob>(restoreJob));
    m_restoreJob->SetJobInfo(jobInfoRestore);
    m_restoreJob->InitJobInfo();
    // Assert
    EXPECT_EQ(m_restoreJob->m_sourceContextMd,
        "source_policy_07bc7411-4193-4a53-a88d-1d1cb6ae51cd/Context");
    EXPECT_EQ(m_restoreJob->m_sourceContext,
        "source_policy_07bc7411-4193-4a53-a88d-1d1cb6ae51cd_Context");
}